package org.example;

import java.lang.reflect.Method;

/**
 * 演示: 通过asm程序生成一个class文件, 并调用其中的方法
 * 整个工程中并没有手写Duck源码.
 * 注意:只有运行了该类的main方法,才会在target/classes目录下,生成com.scy.example.Duck.class文件
 *
 * 对于打包后的jar包,启动方式: jar 和 class 混合启动
 *  java -cp asmTest.jar;asmTest/target/classes org.example.AppGenNewClassByAsm
 *
 * 也可以通过jar包启动
 * java -jar asmTest.jar 但是需要在jar包中的manifest.mf中添加对应的信息
 *
 * 注意:通过asm手动生成字节码的方式很困难,我们可以通过先正向手写源码,再通过
 * ASM bytecode viewer插件来生成目标代码
 * public class Duck {
 *     public String  sayMethod(int age, boolean b,String name) {
 *         System.out.println("firstArg=" + age + ", secondArg=" + b+", ThirdArg=" + name);
 *         System.out.println("Duck...sayMethod is running");
 *         return name + " is Duck,age is " +age;
 *     }
 * }
 *
 *
 */
public class AppGenNewClassByAsm {
    public static void main(String[] args) throws Exception {

        String packageInfo = "com.scy.example";
        String clazzName = "Duck";

        // 生成目标class文件
        CodeGenerationUtil.generateClassFile(packageInfo, clazzName);

        System.out.println("------------使用AppClassLoader加载动态生成的class文件-----------");
        Class<?> duckClass = Class.forName(packageInfo + "." + clazzName);
        Object duck = duckClass.newInstance();
        Method sayMethod = duckClass.getDeclaredMethod("sayMethod",int.class,boolean.class,String.class);
        Object tanglaoya = sayMethod.invoke(duck, 1, false, "tanglaoya");
        System.out.println(tanglaoya);


        System.out.println("------------使用自定义MyClassLoader加载动态生成的class文件-----------");
        String clazzPath = System.getProperty("user.dir") + "/" + CodeGenerationUtil.readConf("conf.properties")
                + CodeGenerationUtil.dot2Slash(packageInfo) + "/" + clazzName + ".class";
        Class<?> aClass = new MyClassLoader().findClass(clazzPath);
        Object o = aClass.newInstance();
        Method sayMethod1 = aClass.getDeclaredMethod("sayMethod",int.class,boolean.class,String.class);
        Object xiaoyazi = sayMethod1.invoke(o, 2, true, "xiaoyazi");
        System.out.println(xiaoyazi);

    }

}
